home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / standards / sgml / nist / parse1 / dtduinp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-13  |  23.5 KB  |  730 lines

  1. /* National Institute of Standards and Technology (NIST)
  2. /* National Computer System Laboratory (NCSL)
  3. /* Office Systems Engineering (OSE) Group
  4. /* ********************************************************************
  5. /*                            D I S C L A I M E R
  6. /*                              (March 8, 1989)
  7. /*  
  8. /* There is no warranty for the NIST NCSL OSE SGML parser and/or the NIST
  9. /* NCSL OSE SGML parser validation suite.  If the SGML parser and/or
  10. /* validation suite is modified by someone else and passed on, NIST wants
  11. /* the parser's recipients to know that what they have is not what NIST
  12. /* distributed, so that any problems introduced by others will not
  13. /* reflect on our reputation.
  14. /* 
  15. /* Policies
  16. /* 
  17. /* 1. Anyone may copy and distribute verbatim copies of the SGML source
  18. /* code as received in any medium.
  19. /* 
  20. /* 2. Anyone may modify your copy or copies of SGML parser source code or
  21. /* any portion of it, and copy and distribute such modifications provided
  22. /* that all modifications are clearly associated with the entity that
  23. /* performs the modifications.
  24. /* 
  25. /* NO WARRANTY
  26. /* ===========
  27. /* 
  28. /* NIST PROVIDES ABSOLUTELY NO WARRANTY.  THE SGML PARSER AND VALIDATION
  29. /* SUITE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
  30. /* EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  31. /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  32. /* THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
  33. /* WITH YOU.  SHOULD THE SGML PARSER OR VALIDATION SUITE PROVE DEFECTIVE,
  34. /* YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
  35. /* 
  36. /* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL NIST BE LIABLE FOR
  37. /* DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
  38. /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
  39. /* INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
  40. /* BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
  41. /* FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
  42. /* NIST) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF
  43. /* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  44. */
  45.  
  46. /************************************************************************/
  47. /*   TITLE:          SGML PARSER                                        */
  48. /*   SYSTEM:         DTD PROCESSOR                                      */
  49. /*   SUBSYSTEM:                                                         */
  50. /*   SOURCE FILE:    DTUINP.C                                           */
  51. /*   AUTHOR:         Jim Heath & Mike Garris                            */
  52. /*                                                                      */
  53. /*   DATE CREATED:                                                      */
  54. /*   LAST MODIFIED:                                                     */
  55. /*                                                                      */
  56. /*                  REVISIONS                                           */
  57. /*   WHEN      WHO            WHY                                       */
  58. /************************************************************************/
  59. #include <stdio.h>
  60. #include <ctype.h>
  61. #include <setjmp.h>
  62. #include "qntyset.h"
  63. #include "dtd.h"
  64. #include "dtdglbl.h"
  65. #include "dtdfncs.h"
  66.  
  67. #define STACKSIZE    1000
  68. int mystack[STACKSIZE];
  69. int stkptr = 0;
  70. static FILE *entfile = NULL;
  71. /* ============================================================ */
  72. /* inpsep() uses jgetc() to input a series of multiple RS's,    */
  73. /* RE's, SPACE's, EE's, and rsolves parameter entity references */
  74. /* processing any sequential occurances of the above in the     */
  75. /* resolving text. The process continues inputing data until    */
  76. /* a character not of the above types is found. Upon which, it  */
  77. /* returns the number of separators encountered. Inpsep() can   */
  78. /* be used for PS's, TS's, and DS's because these above char's  */
  79. /* are common to all three. It is the caller's responsibilty to */
  80. /* impose restrictions and checks according to which separator  */
  81. /* is to be used.                                               */
  82. /* ============================================================ */
  83. inpsep(septype)
  84. int septype;
  85. {
  86.    int c;
  87.    int sepcount = 0;
  88.    for(;;){
  89.       if ((c = jgetc()) == EOF)
  90.          return(EOF);
  91.       switch ((char) c) {
  92.          /* all common to PS's, TS's, and DS's */
  93.       case RS:
  94.       case RE:
  95.       case SPACE:
  96.       case EE:
  97.       case TAB:
  98.          sepcount++;
  99.          break;
  100.          /* must check if parameter entity reference */
  101.       case PERO:
  102.          if ((c = jgetc()) == EOF)
  103.             return(EOF);
  104.          /* if it is a parameter entity reference ...*/
  105.          if(ISALPHA(c)){
  106.             /* set flag to show we are in an entity */
  107.             SETFLAG(IN_ENTITY);
  108.             jungetc(c);
  109.             /* call procedure to resolve reference at separator level */
  110.             reslvpref();
  111.             /* bump separator counter because a parameter entity reference */
  112.             /* is considered a separator */
  113.             sepcount++;
  114.             break;
  115.          }
  116.          /* otherwise, not a parameter entity reference */
  117.          else{
  118.             /* so unget char and PERO, and return */
  119.             jungetc(c);
  120.             jungetc(PERO);
  121.             return(sepcount);
  122.          }
  123.          /* if '-', then check if comment */
  124.       case '-':
  125.          /* if separator type is not PS, then comment can not exist */
  126.          if(septype != PS){
  127.             /* unget '-' and return */
  128.             jungetc(c);
  129.             return(sepcount);
  130.          }
  131.          if ((c = jgetc()) == EOF)
  132.             return(EOF);
  133.          /* otherwise if comment ...*/
  134.          if (c == '-') {
  135.             /* call procedure to input comment */
  136.             inpcomment();
  137.             /* bump separator counter because a comment is a PS */
  138.             sepcount++;
  139.             break;
  140.          }
  141.          /* if not a comment, then unget char and '-' returning */
  142.          jungetc(c);
  143.          jungetc('-');
  144.          return(sepcount);
  145.          /* if non of the above characters, then unget char and return */
  146.       default:
  147.          jungetc(c);
  148.          return(sepcount);
  149.       }
  150.    }
  151. }
  152.  
  153. /* ============================================================ */
  154. /* reslvpref() resolves any parameter entity reference at a     */
  155. /* separator level. It inputs the entity name, searches a table */
  156. /* on the name getting its entity text, and 'ungets' the text   */
  157. /* for further processing.                                      */
  158. /* ============================================================ */
  159. void reslvpref()
  160. {
  161.    char namearray[NAMELEN + 1], *nameptr = namearray;
  162.    char *resptr;
  163.    char tarray[LITLEN + 1], *tptr = tarray;
  164.    int c;
  165.    int synkey;
  166.  
  167.    /* input the parameter entity name */
  168.    if(INPNAME(&nameptr, NAMELEN - 1, noxlat) >= GOOD){
  169.       nameptr = namearray;
  170.       /* search a table for a match on the name returning a */
  171.       /* syntactic literal and the text associated with the name */
  172.       synkey = search(PARM_ENT_NAME, nameptr, &resptr);
  173.       switch(synkey){
  174.          /* if the syntactic literal is 'ILLCHAR' then the */
  175.          /* search was unsuccessful */
  176.       case ILLCHAR:
  177.          syntxerr("Entity Reference not found in table");
  178.          break;
  179.       case KW_PUBLIC:
  180.       case KW_SYSTEM:
  181.          if((c = jgetc()) == EOF)
  182.             terminate(1, "End of File found while resolving parameter entity reference");
  183.          if(c != REFC)
  184.             jungetc(c);
  185.          if (strlen(resptr))
  186.             cknotation(resptr);
  187.          if (strlen(entfilename) == 0) {
  188.             jungetc(EE);
  189.             break;
  190.          }
  191.          entfile = safefopen(entfilename, "r", ENTITYFILE);
  192.          break;
  193.       case KW_MD:
  194.       case KW_STARTTAG:
  195.       case KW_ENDTAG:
  196.          /* if the bracketed text keyword MD was found ... */
  197.          /* add the delimeters to the test string */
  198.          if (synkey == KW_MD)
  199.             sprintf(tptr,"<!%s>",resptr);
  200.          else if (synkey == KW_STARTTAG)
  201.             sprintf(tptr,"<%s>",resptr);
  202.          else if (synkey == KW_ENDTAG)
  203.             sprintf(tptr,"</%s>",resptr);
  204.          if((c = jgetc()) == EOF)
  205.             terminate(1, "End of File found while resolving parameter entity reference");
  206.          if(c != REFC)
  207.             jungetc(c);
  208.          /* call procedure which ungets the text string */
  209.          ungetreslv(tarray);
  210.          break;
  211.       case KW_MS:
  212.          /* add the delimeters to the test string */
  213.          sprintf(tptr,"<![%s]]>",resptr);
  214.          if((c = jgetc()) == EOF)
  215.             terminate(1, "End of File found while resolving parameter entity reference");
  216.          if(c != REFC)
  217.             jungetc(c);
  218.          /* call procedure which ungets the text string */
  219.          ungetreslv(tarray);
  220.          break;
  221.  
  222.          /* ***** must also add cases for STARTTAG and ENDTAG ***** */
  223.  
  224.          /* if syntactic literal is NULL, then entity text consists */
  225.          /* of only a parameter literal */
  226.       case NULL:
  227.          if((c = jgetc()) == EOF)
  228.             terminate(1, "End of File found while resolving parameter entity reference");
  229.          if(c != REFC)
  230.             jungetc(c);
  231.          /* unget parameter literal */
  232.          ungetreslv(resptr);
  233.          break;
  234.          /* any other syntactic literal is illegal */
  235.       default:
  236.          syntxerr("Illegal use of syntactic literal in a PS entity reference");
  237.          break;
  238.       }
  239.    }
  240.    else
  241.       syntxerr("Reference name not found in PS entity reference");
  242. }
  243.  
  244. /* ============================================================ */
  245. /* ungetreslv() puts a text string onto the "unget" stack in    */
  246. /* reverse order. First pushing an EE onto the stack marking    */
  247. /* the end of and enitity text.                                 */
  248. /* ============================================================ */
  249. void ungetreslv(resptr)
  250. char *resptr;
  251. {
  252.    int len;
  253.    REGISTER char *endptr = resptr;
  254.  
  255.    len = strlen(resptr);
  256.    jungetc(EE);
  257.    if(len > 0){
  258.       endptr += len - 1;
  259.       while(endptr != resptr)
  260.          jungetc(*endptr--);
  261.       jungetc(*endptr);
  262.    }
  263. }
  264. /* ============================================================ */
  265. inpitem(recptr, len, firstchar, remchar, xlat, rniflag)
  266. char **recptr;
  267. int len;
  268. int (*firstchar)(), (*remchar)(), (*xlat)();
  269. int rniflag;
  270. {
  271.    char tmparray[NAMELEN + 2], *tbuff = tmparray;
  272.    char *temp = *recptr;
  273.    REGISTER int c, j;
  274.    int ccount = 0, index;
  275.  
  276.    if(len > NAMELEN)
  277.       terminate(1, "length exceeds NAMELEN in getitem()");
  278.    if ((c = (*xlat)(jgetc())) == EOF)
  279.       return(EOF);
  280.    ccount++;
  281.    if (rniflag == YES)
  282.       if (c == RNI) {
  283.          len++;
  284.          xlat = TOUPPER;
  285.          goto L1;
  286.       }
  287.    if (!(*firstchar)(c)) {
  288.       jungetc(c);
  289.       return(BAD);
  290.    }
  291. L1:
  292.    *tbuff++ = c;
  293.    while (--len) {
  294.       if ((c = (*xlat)(jgetc())) == EOF)
  295.          return(EOF);
  296.       if ((*remchar)(c)) {
  297.          ccount++;
  298.          *tbuff++ = c;
  299.       }
  300.       else {
  301.          jungetc(c);
  302.          break;
  303.       }
  304.    }
  305.    if ((c = (*xlat)(jgetc())) == EOF)
  306.       return(EOF);
  307.    jungetc(c);
  308.    if ((*remchar)(c)) {
  309.       for (; ccount > 0; ccount--)
  310.          jungetc(tmparray[ccount]);
  311.       return(BAD);
  312.    }
  313.    for (j = 0; j < ccount; j++)
  314.       *temp++ = tmparray[j];
  315.    *temp = '\0';
  316.    index = getkwindex(*recptr);
  317.    *recptr = temp;
  318.    return(index);
  319. }
  320. /* ============================================================ */
  321. void inpcomment()
  322. {
  323.    REGISTER int c;
  324.    for(;;) {
  325.       if ((c = jgetc()) == EOF)
  326.          terminate(1, "EOF found while processing comment");
  327.       if (c != '-')
  328.          continue;
  329.       if ((c = jgetc()) == EOF)
  330.          terminate(1, "EOF found while processing comment");
  331.       if (c == '-')
  332.          return;
  333.    }
  334. }
  335. /* ============================================================ */
  336. int inpMDO()
  337. {
  338.    REGISTER int c;
  339.  
  340.    if ((c = jgetc()) == EOF)
  341.       return(EOF);
  342.    if (c != '<') {
  343.       jungetc(c);
  344.       return(BAD);
  345.    }
  346.    if ((c = jgetc()) == EOF)
  347.       return(EOF);
  348.    if (c != '!') {
  349.       jungetc(c);
  350.       jungetc('<');
  351.       return(BAD);
  352.    }
  353.    ADDCHAR('<');
  354.    ADDCHAR('!');
  355.    return(GOOD);
  356. }
  357.  
  358. /* ============================================================ */
  359. /* inpparmlit() inputs a parameter literal delemeted by either  */
  360. /* LIT's or LITA's. It only recognizes PERO's ans CRO's as      */
  361. /* mark-up due to the standards definition of replaceable       */
  362. /* parameter data.                                              */
  363. /* ============================================================ */
  364. void inpparmlit(litptr)
  365. char **litptr;
  366. {
  367.    int delimeter, len = 0;
  368.    REGISTER int c, d;
  369.    char *lptr = *litptr;
  370.    int refflag = 0; /* flag if 1 => parameter entity reference found in */
  371.    /*              parameter literal with unmatch EE */
  372.    /*      if 0 => no unmatched reference currently in */
  373.    /*              parameter literal */
  374.  
  375.    if((c = jgetc()) == EOF)
  376.       terminate(1, "End of File found while processing parameter literal");
  377.    /* if LIT then delimeter is LIT */
  378.    if(c == LIT)
  379.       delimeter = LIT;
  380.       /* else delimeter is LITA */
  381.    else
  382.       if(c == LITA)
  383.          delimeter = LITA;
  384.       else{
  385.          ADDCHAR(c);
  386.          jungetc(c);
  387.          syntxerr("Delimeter not found in parameter literal");
  388.       }
  389.    /* while closeing delimeter not found ...*/
  390.    while((c = jgetc()) != delimeter){
  391.       switch ((char) c){
  392.       case EE:
  393.          /* EE found not matching any existing reference within par. lit. */
  394.          if(refflag == 0)
  395.             syntxerr("EE found terminating reference not occurring within parameter literal");
  396.          refflag = 0;
  397.          break;
  398.          /* if PERO, then check if entity reference */
  399.       case PERO:
  400.          if ((c = jgetc()) == EOF)
  401.             terminate(1, "End of File found while interpreting parameter literal");
  402.          /* if reference ... */
  403.          if(ISALPHA(c)){
  404.             jungetc(c);
  405.             /* call procedure to resolve parameter entity reference within */
  406.             /* replaceable parameter data */
  407.             reslvreplpref(&lptr, &len);
  408.             /* set flag to unmatched reference found in parameter literal */
  409.             refflag = 1;
  410.          }
  411.          else{
  412.             /* otherwise, no reference, so treat PERO as char data */
  413.             *lptr++ = PERO;
  414.             *lptr++ = c;
  415.             *lptr = '\0';
  416.             len += 2;
  417.          }
  418.          break;
  419.          /* if '&', then check if character reference */
  420.       case '&':
  421.          if((c = jgetc()) == '#') {
  422.             if ((d = jgetc()) == EOF)
  423.                terminate(1, "End of File found while interpreting parameter literal");
  424.             if(ISDIGIT(d) || isnmstrt(d)) {
  425.                jungetc(d);
  426.                /* if CRO, then call procedure to resolve char reference */
  427.                reslvcharref(&lptr, &len);
  428.             }
  429.             else{
  430.                *lptr++ = '&';
  431.                *lptr++ = c;
  432.                *lptr++ = d;
  433.                *lptr = '\0';
  434.                len += 3;
  435.             }
  436.          }
  437.          /* otherwise, treat '&' as char data */
  438.          else{
  439.             jungetc(c);
  440.             *lptr++ = '&';
  441.             *lptr = '\0';
  442.             len += 1;
  443.          }
  444.          break;
  445.          /* default => char data */
  446.       default:
  447.          *lptr++ = c;
  448.          *lptr = '\0';
  449.          len++;
  450.          break;
  451.       }
  452.       /* if length of interpretted parameter literal */
  453.       /*  exceeds LITLEN then ERROR */
  454.       if(len > LITLEN){
  455.          ADDCHAR(LIT);
  456.          ADDSTRING(lptr);
  457.          syntxerr("LITLEN is exceeded in parameter literal");
  458.       }
  459.    }
  460.    ADDCHAR(LIT);
  461.    ADDSTRING(*litptr);
  462.    ADDCHAR(LIT);
  463.    *litptr = lptr;
  464. }
  465.  
  466. /* ============================================================ */
  467. /* reslvcharref() resolves character references. It determines  */
  468. /* if character reference consists of a function name or char   */
  469. /* number. If reference consists of a character number, then    */
  470. /* an a to i translation routine is called and appropriate      */
  471. /* character is added to the literal string.                    */
  472. /* ============================================================ */
  473. void reslvcharref(litptr, lenptr)
  474. char **litptr;
  475. int *lenptr;
  476. {
  477.    REGISTER int j;
  478.    char namearray[NAMELEN + 1], *nameptr = namearray;
  479.    char *lptr = *litptr;
  480.  
  481.    /* input name */
  482.    if((j = INPNAME(&nameptr, NAMELEN, TOUPPER)) >= GOOD){
  483.       switch (j){
  484.          /* if name is valid then assume char reference containing function name*/
  485.       case RE:
  486.          *lptr++ = RE;
  487.          *lptr = '\0';
  488.          *lenptr = *lenptr + 1;
  489.          break;
  490.       case RS:
  491.          *lptr++ = RS;
  492.          *lptr = '\0';
  493.          *lenptr = *lenptr + 1;
  494.          break;
  495.       case SPACE:
  496.          *lptr++ = SPACE;
  497.          *lptr = '\0';
  498.          *lenptr = *lenptr + 1;
  499.          break;
  500.          /* if any other name found then ERROR */
  501.       default:
  502.          ADDSTRING(synliteral(j));
  503.          syntxerr("Unknown function name in character reference");
  504.          break;
  505.       }
  506.    }
  507.    /* otherwise, no name found, so assume character number */
  508.    else{
  509.       if((j = jgetc()) == EOF)
  510.          terminate(1, "End of File found while resolving character reference");
  511.       /* if next character inputted is not numeric then ERROR */
  512.       if(ISALPHA(j)){
  513.          ADDCHAR(j);
  514.          jungetc(j);
  515.          syntxerr("Character number expected while resolving character reference");
  516.       }
  517.       jungetc(j);
  518.       /* otherwise call procedure to add character represented to lit string */
  519.       xlatcharnum(&lptr, lenptr);
  520.    }
  521.    if((j = jgetc()) == EOF)
  522.       terminate(1, "End of File found while resolving character reference");
  523.    if(j != REFC)
  524.       jungetc(j);
  525.    *litptr = lptr;
  526. }
  527.  
  528. /* ============================================================ */
  529. /* xlatcharnum() inputs an ascii number string and converts it  */
  530. /* to its character equivalent adding it to the literal string. */
  531. /* ============================================================ */
  532. void xlatcharnum(litptr, lenptr)
  533. char **litptr;
  534. int *lenptr;
  535. {
  536.    REGISTER int j;
  537.    int xlatcharnum;
  538.    char *lptr = *litptr, charnum[MAX_CHAR_IN_DELIM_NUM + 1];
  539.    REGISTER char *cptr = charnum;
  540.  
  541.    if((j = jgetc()) == EOF)
  542.       terminate(1, "End of File found while resolving character reference");
  543.    if(!ISDIGIT(j)){
  544.       ADDCHAR(j);
  545.       jungetc(j);
  546.       syntxerr("Character number not found in resolving character reference");
  547.    }
  548.    while(ISDIGIT(j)){
  549.       *cptr++ = j;
  550.       *cptr = '\0';
  551.       if((j = jgetc()) == EOF)
  552.          terminate(1, "End of File found while resolving character reference");
  553.    }
  554.    jungetc(j);
  555.    xlatcharnum = atoi(charnum);
  556.    *lptr++ = xlatcharnum;
  557.    *lptr = '\0';
  558.    *lenptr = *lenptr + 1;
  559.    *litptr = lptr;
  560. }
  561.  
  562. /* ============================================================ */
  563. /* reslvreplpref() resolves parameter entity references within  */
  564. /* replaceable parameter data. It inputs the reference name,    */
  565. /* searches a table on the name, and adds then entity text to   */
  566. /* the interpretted literal string.                             */
  567. /* ============================================================ */
  568. void reslvreplpref(litptr, lenptr)
  569. char **litptr;
  570. int *lenptr;
  571. {
  572.    REGISTER char *lptr = *litptr;
  573.    char namearray[NAMELEN + 1], *nameptr = namearray;
  574.    int c, len;
  575.    char *resptr;
  576.    int synkey;
  577.  
  578.    /* input name */
  579.    if(INPNAME(&nameptr, NAMELEN - 1, noxlat) >= GOOD){
  580.       nameptr = namearray;
  581.       synkey = search(PARM_ENT_NAME, nameptr, &resptr);
  582.       switch(synkey){
  583.          /* if syntactic literal is MD then add appropriate delimeters */
  584.          /* to resolved text */
  585.       case KW_MD:
  586.          *lptr++ = '<';
  587.          *lptr++ = '!';
  588.          strcat(lptr, resptr);
  589.          len = strlen(resptr);
  590.          lptr += len;
  591.          *lptr++ = MDC;
  592.          *lptr = '\0';
  593.          len += 3;
  594.          break;
  595.  
  596.          /* ***** add bracketed text keywords STARTTAG, ENDTAG, and MD ***** */
  597.  
  598.          /* if syntactic literal is 'ILLCHAR' then search unsuccessful */
  599.       case ILLCHAR:
  600.          syntxerr("Entity reference not found in table");
  601.          break;
  602.          /* if syntactic literal is NULL, then entity text consists of */
  603.          /* parameter literal only */
  604.       case NULL:
  605.          strcat(lptr, resptr);
  606.          len = strlen(resptr);
  607.          lptr += len;
  608.  
  609.          /*           *lptr++ = EE;*/
  610.          *lptr = '\0';
  611.  
  612.          break;
  613.          /* any other syntactic literal found is ERROR */
  614.       default:
  615.          syntxerr("Unknown syntactic literal in parameter entity reference.");
  616.          break;
  617.       }
  618.    }
  619.    else
  620.       syntxerr("Reference name not found while resolving parameter entity reference.");
  621.    /* increment length of interpretted literal by length of entity text */
  622.    *lenptr = *lenptr + len;
  623.    if((c = jgetc()) == EOF)
  624.       terminate(1, "End of File found while resolving parameter entity referecne");
  625.    if(c != REFC)
  626.       jungetc(c);
  627.    *litptr = lptr;
  628. }
  629. /* ============================================================ */
  630. int jgetc()
  631. {
  632.    extern int debug;
  633.    REGISTER int temp;
  634.    if(stkptr > 0)
  635.       temp = mystack[--stkptr];
  636.    else if (entfile != NULL)
  637.       temp = getc(entfile);
  638.    else
  639.       temp = getc(docfile);
  640.    if ((temp == CTRLZ) || (temp == EOF)) {
  641.       if (entfile != NULL) {
  642.          safefclose(entfile, entfilename, ENTITYFILE);
  643.          entfile = NULL;
  644.          temp = EE;
  645.       }
  646.       else
  647.          temp = EOF;
  648.    }
  649.    if (debug & 1) {
  650.       if ((temp > ' ') && (temp < 0x7f))
  651.          printf("jgetc returns %c\n", temp);
  652.       else
  653.          printf("jgetc returns 0x%02x\n", temp);
  654.    }
  655.    if ((char) temp == EE){
  656.       CLEARFLAG(IN_ENTITY);
  657.       if (TESTFLAG(IN_DECL) && TESTFLAG(DECL_IS_IN_ENTITY))
  658.          syntxerr("illegal parameter entity reference");
  659.    }
  660.    return(temp);
  661. }
  662. /* ============================================================ */
  663. void jungetc(c)
  664. REGISTER int c;
  665. {
  666.    extern int debug;
  667.    if (debug & 1) {
  668.       if ((c > ' ') && (c < 0x7f))
  669.          printf("jungetc returns %c\n", c);
  670.       else
  671.          printf("jungetc returns 0x%02x\n", c);
  672.    }
  673.    if(stkptr >= STACKSIZE)
  674.       terminate(1,"User Stack Over-Flow!");
  675.    mystack[stkptr++] = c;
  676. }
  677. /* ============================================================ */
  678. void stackinit()
  679. {
  680.    stkptr = 0;
  681. }
  682.  
  683. /* ============================================================ */
  684. /* getkwindex() returns the defined string equivalent of an     */
  685. /* inputted integer.                                            */
  686. /* ============================================================ */
  687. int getkwindex(s)
  688. char *s;
  689. {
  690.    REGISTER int jj;
  691.    char *j, *k = s;
  692.    char chararray[NAMELEN + 1];
  693.    static char *keywords[] = {
  694.       "DOCTYPE", "ELEMENT", "ENTITY", "RNIDEFAULT",
  695.       "ANY", "CDATA", "RCDATA", "SDATA", "PI", "EMPTY",
  696.       "STARTTAG", "ENDTAG", "MS", "MD", "ATTLIST",
  697.       "ID", "IDREF", "IDREFS", "NAME", "NAMES",
  698.       "NMTOKEN", "NMTOKENS", "NOTATION", "NUMBER",
  699.       "NUMBERS", "NUTOKEN", "NUTOKENS", "#REQUIRED",
  700.       "#CURRENT", "#CONREF", "#IMPLIED", "#FIXED","",
  701.       "","","SYSTEM", "PUBLIC", "NDATA"         };
  702. #define MAXKEYWORDS ((sizeof(keywords))/(sizeof(char *)))   
  703.    static int keytokens[] = 
  704.    {
  705.       KW_DOCTYPE, KW_ELEMENT, KW_ENTITY, KW_RNIDEFAULT,
  706.       KW_ANY, KW_CDATA, KW_RCDATA, KW_SDATA, KW_PI, KW_EMPTY,
  707.       KW_STARTTAG, KW_ENDTAG, KW_MS, KW_MD, KW_ATTLIST,
  708.       KW_ID, KW_IDREF, KW_IDREFS, KW_NAME, KW_NAMES,
  709.       KW_NMTOKEN, KW_NMTOKENS, KW_NOTATION, KW_NUMBER,
  710.       KW_NUMBERS, KW_NUTOKEN, KW_NUTOKENS, KW_REQUIRED,
  711.       KW_CURRENT, KW_CONREF, KW_IMPLIED, KW_FIXED, KW_GROUP,
  712.       KW_LIT, KW_UNFIXED, KW_SYSTEM, KW_PUBLIC, KW_NDATA       };
  713.  
  714.    for (jj = 0; jj < MAXKEYWORDS; jj++) {
  715.       if(strcmp(s, keywords[jj]) == 0)
  716.          return(keytokens[jj]);
  717.    }
  718.    if (strcmp(s, "RE") == 0)
  719.       return(RE);
  720.    if (strcmp(s, "RS") == 0)
  721.       return(RS);
  722.    if (strcmp(s, "SPACE") == 0)
  723.       return(SPACE);
  724.  
  725.    for(j = chararray; (*j = TOUPPER(*k)) != EOS; j++, k++);
  726.    if(strcmp(chararray, "#DEFAULT") == 0)
  727.       return(KW_RNIDEFAULT);
  728.    return(GOOD);
  729. }
  730.